//
// Ephi - simulation of magnetic fields and particles
// Copyright (C) 2007 Indrek Mandre <indrek(at)mare.ee>
// For more information please see http://www.mare.ee/indrek/
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//

#ifndef __config_hpp__
#define __config_hpp__

#include <vector>
#include <string>
#include <list>
#include <map>

#include "math3d.hpp"

/** Configuration reading for the main polywell simulation application. */
class Config
{
public:
  void reg_num (const char *group, const char *name, prec_t deflt = 0.0);
  void reg_vect3d (const char *group, const char *name, const vect3d& dflt = vect3d(0, 0, 0));
  void reg_bool (const char *group, const char *name, bool dflt = false);
  void reg_enum (const char *group, const char *name, const char *dflt, ...);
  void reg_str (const char *group, const char *name, const char *dflt = "");

  bool select_group (const char *name, size_t index);

  const char * get_str (const char *name);
  const char * get_enum (const char *name);
  prec_t get_prec (const char *name);
  size_t get_size (const char *name);
  vect3d& get_vect3d (const char *name, vect3d& res);
  bool get_bool (const char *name);

  bool load (const char *path);

private:

  struct type_t;

  struct value_t
  {
    value_t() : value_prec(0) { }
    type_t *t;
    prec_t value_prec;
    vect3d value_vect3d;
    bool value_bool;
    std::string value_enum;
    std::string value_str;
  };

  struct group_t;

  struct type_t
  {
    enum et { PREC, VECT3D, BOOL, ENUM, STR };
    et t;
    std::string name;
    group_t *group;
    std::list<std::string> enums;
    value_t dflt;
  };

  typedef std::map<std::string, type_t> types_t;
  types_t types;

  typedef std::map<std::string, value_t> values_t;

  struct group_t
  {
    group_t() : ref(0) { }
    std::string name;
    std::vector<values_t> instances;
    values_t *ref;
  };

  typedef std::map<std::string, group_t> groups_t;
  groups_t groups;

  value_t& get_value (const char *name, type_t::et t);
};

#endif // !__config_hpp__

